﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace My_Calculator
{
    public partial class Calculator : Form
    {
        //标记计算器是否开始工作
        public enum status 
        {
            welcome,
            begin,
            end,
            error,
        };
        //标记上一次输入的是数字还是操作符
        public enum type_tag
        {
            number,
            operators,

        };
        //标记上一次输入的是哪一个操作符
        public enum type_operator
        {
            operator_add,
            operator_sub,
            operator_mul,
            operator_div,
            operator_equal,
        };
        protected status cal_status = status.welcome;
        protected type_tag last_input = type_tag.number;
        protected type_operator last_operator = type_operator.operator_add;
        protected double data_current = 0;
        protected double data_result = 0;

        public Calculator()
        {
            InitializeComponent();
            this.panel_cal.Hide();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (cal_status == status.welcome)
            {
                this.label_Welcom.Text = "sorry,\"傻瓜\"计算器傻了……";
                Image pic_error = null;
                try
                {
                    pic_error = Image.FromFile("..\\..\\Resources\\error.jpg");
                }
                catch (Exception)
                {
                    MessageBox.Show("找不到图片资源");
                }

                if (pic_error != null)
                {
                    this.label_Pic.Image = pic_error;
                }
                else
                {
                    MessageBox.Show("找不到图片资源");
                }
                this.button1.Text = "骗人";
                cal_status = status.begin;
            }
            else if (cal_status == status.begin)
            {
                this.panel_welcome.Hide();
                this.panel_cal.Show();
                this.label_input.Text = "0";
                cal_status = status.end;
            }
            this.label_input.Focus();
        }

        //所有数字键和小数点都调用此函数
        private void button_input(object sender, EventArgs e)
        {
            //在出错状态禁止输入
            if (cal_status == status.error)
            {
                this.label_input.Focus();
                return;
            }
            //执行一次清除键操作，从原始状态重新工作。
            if (last_operator == type_operator.operator_equal)
            { 
                button_c_Click(sender, e);
            }

            //num用以获取当前输入的数字
            string num = "";
            if (sender.Equals(this.button_pt))
            {
                num = ".";
            }
            else 
            {
                num = (sender as Button).Name[7].ToString();
            }

            //连续输入数字
            if (last_input == type_tag.number)
            {
                //不允许首先输入多个0
                if (this.label_input.Text == "0" && num == "0")
                {
                    this.label_input.Focus();
                    return;
                }
                //不允许输入多个小数点
                if (this.label_input.Text.IndexOf(".") != -1 && num == ".")
                {
                    this.label_input.Focus();
                    return;
                }
                //去掉整数数字前面的0
                if (this.label_input.Text == "0" && num != ".")
                {
                    this.label_input.Text = num;
                }
                else
                {
                    this.label_input.Text += num;
                }
                //如果输入的是小数点，不对tata_current做操作
                if (num != ".")
                {
                     data_current = Double.Parse(this.label_input.Text);
                }
            }
            //操作符之后输入数字
            else
            {
                if (num == ".")
                {
                    this.label_input.Text = "0" + num;
                    data_current = 0;
                }
                else
                {
                    this.label_input.Text = num;
                    data_current = Double.Parse(num);
                }
            }
            last_input = type_tag.number;
            this.label_input.Focus();
        }

        //清楚键C
        private void button_c_Click(object sender, EventArgs e)
        {
            this.label_input2.Text = "";
            last_input = type_tag.number;
            last_operator = type_operator.operator_add;
            cal_status = status.end;
            data_current = 0;
            data_result = 0;
            this.label_input.Text = "0";
            this.label_input.Focus();
        }

        //加减乘除按钮的操作
        private void button_operator_Click(object sender, EventArgs e)
        {
            //在出错状态禁止输入
            if (cal_status == status.error)
            {
                this.label_input.Focus();
                return;
            }
            //等号操作后紧接着输入操作符的特殊处理
            if (last_operator == type_operator.operator_equal)
            {
                data_current = data_result;
                data_result = 0;
                last_input = type_tag.number;
                last_operator = type_operator.operator_add;
            }

            type_operator this_operator = type_operator.operator_add;
            string this_text = "";
            switch ((sender as Button).Name)
            {
                case "button_plus" :
                    this_operator = type_operator.operator_add; 
                    this_text = " + "; break;
                case "button_sub":
                    this_operator = type_operator.operator_sub;
                     this_text = " - "; break;
                case "button_mul":
                    this_operator = type_operator.operator_mul;
                     this_text = " * "; break;
                case "button_div":
                    this_operator = type_operator.operator_div;
                     this_text = " / "; break;
                case "button_equal":
                     this_operator = last_operator;
                     break;
            }

            //忽略重复操作
            if (last_input == type_tag.operators && last_operator == this_operator)
            {
                this.label_input.Focus();
                return;  
            }
            //修改已输入的操作符
            else if (last_input == type_tag.operators && last_operator != this_operator)
            {
                this.label_input2.Text = this.label_input2.Text.Substring(0, 
                    this.label_input2.Text.Length - 3);
                this.label_input2.Text += this_text;
                last_input = type_tag.operators;
                last_operator = this_operator;
                this.label_input.Focus();
                return;
            }

            //正常的输入计算
            data_result = pre_account(last_operator, data_current, data_result);
            this.label_input2.Text += data_current.ToString();
            this.label_input2.Text += this_text;
            if (double.IsNegativeInfinity(data_result)||double.IsPositiveInfinity(data_result))
            {
                this.label_input.Text = "除数不能为0";
                cal_status = status.error;
            }
            else
            {
                this.label_input.Text = data_result.ToString();
                last_input = type_tag.operators;
                last_operator = this_operator;
            }
            this.label_input.Focus();
        }

        //计算结果
        private double pre_account(type_operator last_operator, double data_current, double data_result)
        {
            switch (last_operator)
            {
                case type_operator.operator_add:
                    data_result += data_current; break;
                case type_operator.operator_sub:
                    data_result -= data_current; break;
                case type_operator.operator_mul:
                    data_result *= data_current; break;
                case type_operator.operator_div:
                    data_result /= data_current; break;
            }
            return data_result;
        }

        //等号操作符的计算
        private void button_equal_Click(object sender, EventArgs e)
        {
            //在出错状态禁止输入
            if (cal_status == status.error)
            {
                this.label_input.Focus();
                return;
            }
            //操作符之后直接输入等号
            if (last_input == type_tag.operators)
            {
                last_input = type_tag.number;
                data_current = data_result;
            }
            button_operator_Click(sender, e);
            this.label_input2.Text = "";
            last_operator = type_operator.operator_equal;
            this.label_input.Focus();
        }

        //回退按键
        private void button_back_Click(object sender, EventArgs e)
        {
            //在出错状态禁止输入
            if (cal_status == status.error)
            {
                this.label_input.Focus();
                return;
            }
            //如果不是数字输入状态或者只剩下一个0则不相应操作
            if (last_input != type_tag.number || this.label_input.Text == "0")
            {
                this.label_input.Focus();
                return;
            }
            else
            {
                this.label_input.Text = this.label_input.Text.Substring(0, this.label_input.Text.Length - 1);
            }

            //如果回退后只剩下一个负号或空则显示为0
            if (this.label_input.Text == "-" || this.label_input.Text == "")
            {
                this.label_input.Text = "0";
                data_current = 0;
                this.label_input.Focus();
                return;
            }

            //如果回退后最后一个数字是小数点
            if (this.label_input.Text.Substring(this.label_input.Text.Length - 1, 1) == ".")
            {
                data_current = Double.Parse(this.label_input.Text.Substring(0,
                    this.label_input.Text.Length - 1));
            }

            data_current = Double.Parse(this.label_input.Text);
            this.label_input.Focus();
        }

        //CE按键
        private void button_CE_Click(object sender, EventArgs e)
        {
            //在出错状态禁止输入
            if (cal_status == status.error)
            {
                this.label_input.Focus();
                return;
            }
            this.label_input.Text = "0";
            data_current = 0;
            last_input = type_tag.number;
            this.label_input.Focus();
        }

        // 接收键盘输入
        private void form_Cal_KeyDown(object sender, KeyEventArgs e)
        {
            string sub_buttonname = "";
            object[] temp_senders = null;
            object fake_sender = null;
            Console.WriteLine((int)e.KeyCode);

            //获取输入的各种操作符、小数点对应的控键名
            switch (e.KeyCode)
            {
                case Keys.Decimal:
                    sub_buttonname = "pt"; break;
                case Keys.OemPeriod:
                    sub_buttonname = "pt"; break;

                case Keys.Add:
                    sub_buttonname = "plus"; break;

                case Keys.Subtract:
                    sub_buttonname = "sub"; break;
                case Keys.OemMinus:
                    sub_buttonname = "sub"; break;

                case Keys.Multiply:
                    sub_buttonname = "mul"; break;

                case Keys.Divide:
                    sub_buttonname = "div"; break;
                case Keys.OemQuestion:
                    sub_buttonname = "div"; break;

                case Keys.Oemplus:
                    sub_buttonname = "equal"; break;
                case Keys.Enter:
                    sub_buttonname = "equal"; break;
                case Keys.Separator:
                    sub_buttonname = "equal"; break;

                case Keys.Escape:
                    sub_buttonname = "c"; break;
                case Keys.Delete:
                    sub_buttonname = "CE"; break;
                case Keys.Back:
                    sub_buttonname = "back"; break;
            }

            //获取数字键的控件名
            if (57 >= (int)e.KeyCode && (int)e.KeyCode >= 48)
            {
                sub_buttonname = ((int)e.KeyCode - 48).ToString(); 
            }
            else if(105 >= (int)e.KeyCode && (int)e.KeyCode >= 96)
            {
                sub_buttonname = ((int)e.KeyCode - 96).ToString(); 
            }

            //处理组合键输入+*的情况
            if (e.Shift && e.KeyCode == Keys.D8)
            {
                sub_buttonname = "mul";
            }
            else if (e.Shift && e.KeyCode == Keys.Oemplus)
            {
                sub_buttonname = "plus";
            }

            //如果输入的按键不是计算器所需要的则不处理
            if(sub_buttonname == "")
            {
                this.label_input.Focus();
                return;
            }
            temp_senders = Controls.Find("button_" + sub_buttonname, true);
            if (temp_senders != null)
            {
                fake_sender = temp_senders[0];
                //如果不存在这种控件则不处理
                if (fake_sender == (object)null)
                {
                    this.label_input.Focus();
                    return;
                }
            }

            //数字键和小数点
            if (!e.Shift && (48 <= (int)e.KeyCode && (int)e.KeyCode <= 57) || sub_buttonname == "pt" ||
                (96 <= (int)e.KeyCode && (int)e.KeyCode <= 105))
            {
                button_input(fake_sender, null);
            }
            //数字键加减乘除
            else if (sub_buttonname == "plus" || sub_buttonname == "sub" || 
                sub_buttonname == "mul" || sub_buttonname == "div")
            {
                button_operator_Click(fake_sender, null);
            }
            //等号
            else if (sub_buttonname == "equal")
            {
                button_equal_Click(fake_sender, null);
            }
            //清楚键C
            else if (sub_buttonname == "c")
            {
                button_c_Click(fake_sender, null);
            }
            //清楚当前输入CE
            else if (sub_buttonname == "CE")
            {
                button_CE_Click(fake_sender, null);
            }
            //回退键
            else if (sub_buttonname == "back")
            {
                button_back_Click(fake_sender, null);
            }
        }
    }
}
